home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / UTILITY / CMDED2E6.ARJ / EDIT.ASM < prev    next >
Assembly Source File  |  1992-06-30  |  30KB  |  1,163 lines

  1. ; EDIT.ASM
  2. ; (c) 1989, 1990 Ashok P. Nadkarni
  3. ;
  4. ; This module contains the line editing functions of CMDEDIT.
  5. ; Macro disable toggle added by dfa,  December 1990.
  6. ; Ability to switch ESC to filename completion added by dfa, May 1991.
  7. ; Twiddle key and filename display added by wd.
  8. ; Disable backslash appending to directory name added by dfa,  June 1992.
  9. ; Tab completion cycling added by wd and dfa,  June 1992.
  10.  
  11.     PUBLIC    get_kbd_line
  12.     PUBLIC    auto_recall
  13.     PUBLIC    expand_fnkey
  14.     PUBLIC    BKS_key_function    ;Added by wd
  15.     PUBLIC    ESC_key_function    ;Added by dfa
  16.     PUBLIC    TAB_key_function    ;Added by dfa
  17.     PUBLIC    backslash_char        ;Added by dfa & wd
  18.     PUBLIC    getkey_funcnum        ;Added by wd
  19.  
  20.     INCLUDE common.inc
  21.     INCLUDE buffers.inc        ;Added by wd
  22.     INCLUDE ascii.inc
  23.     INCLUDE    BIOS.INC
  24.     INCLUDE    DOS.INC
  25.     INCLUDE    GENERAL.INC
  26.  
  27.  
  28. CSEG    SEGMENT    PARA PUBLIC 'CODE'
  29. CSEG    ENDS
  30.  
  31. DGROUP    GROUP    CSEG
  32.  
  33.     ASSUME    CS:DGROUP, DS:DGROUP, SS:DGROUP, ES:DGROUP
  34.  
  35. CSEG    SEGMENT    PARA PUBLIC 'CODE'
  36.  
  37.     EXTRN    linebuf:BYTE
  38.     EXTRN    lastchar:WORD
  39.     EXTRN    caller_cursor:WORD
  40.     EXTRN    dot:WORD
  41.     EXTRN    edit_mode:BYTE
  42.     EXTRN    omode_cursor:WORD
  43.     EXTRN    disable_macro:BYTE    ;added by dfa
  44.     EXTRN    initial_currow:BYTE    ;added by wd
  45.     EXTRN    sym_stk:WORD
  46.     EXTRN    LINEBUF_END:ABS
  47.  
  48. ; These 7 lines added by wd
  49. FFBLK_SAVE_SIZE equ    30
  50. ffblk_save    db    FFBLK_SAVE_SIZE dup (?)
  51.  
  52. CycleFlags    db    0        ;bit 0 == 1 if cmd is cycle_complete
  53.                     ;bit 1 == 1 if last cmd was ''
  54. fnameptr    dw    0        ;fname location in linebuf    
  55. olddot        dw    0        ;Remember where dot was
  56.  
  57. tempchar db    ?            ;Temporary storage
  58. auto_recall    db    0        ;By default no auto recall
  59. auto_recall_on    db    ?        ;1 if auto-recall in effect,
  60. ;                     else 0
  61. continue_recall db    ?        ;auto-recall state variable
  62. backslash_char    db    '\'        ;added by dfa & wd
  63. fnkey_tab    db    'S','F',0    ;Used to look for function key
  64. ;                     definitions. 
  65. fnkey_exec_char db    '@'        ;If the last character a fn key
  66. ;                     definition is this, the key is
  67. ;                     executed immediately
  68. getkey_funcnum    db    8        ;what function to use for getkey
  69.  
  70. ; Must be IDENTICAL to the string in CMDCONF.C including the
  71. ; terminating '\0' byte. This must be followed immediately by ctrl_key_defs.
  72. cmdedit_keymap_id db    'CMDEDIT key map',0
  73. ; ctrl_key_redefs is used to allow the cmdconf program to remap the control
  74. ; keys. Each entry corresponds to a control key. It must immediately follow
  75. ; cmdedit_keymap_id.
  76. ctrl_key_redefs LABEL WORD
  77. x    =    0
  78.     REPT    32                ;32 control keys
  79.     DW    x
  80. x    =    x + 1
  81.     ENDM
  82.  
  83.  
  84.     EXTRN    disp_line:PROC
  85.     EXTRN    hist_back:PROC
  86.     EXTRN    hist_fwd:PROC
  87.     EXTRN    hist_bck_match:PROC
  88.     EXTRN    hist_fwd_match:PROC
  89.     EXTRN    remember:PROC
  90.     EXTRN    execute_auto_recall:PROC
  91.     EXTRN    insert_at_dot:PROC
  92.     EXTRN    erase_to_dot:PROC
  93.     EXTRN    isalphnum:PROC
  94.     EXTRN    set_disp_marks:PROC
  95.     EXTRN    bell:PROC
  96.     EXTRN    line_to_scr:PROC
  97.     EXTRN    isspace:PROC
  98.     EXTRN    xlate_lower:PROC
  99.     EXTRN    expand_var:PROC
  100.     EXTRN    ismacsym:PROC
  101.     EXTRN    get_symbol:PROC
  102.     EXTRN    tolower:PROC        ;added by wd
  103.     EXTRN    disp_prompt:PROC    ;added by wd
  104.     EXTRN    get_curpos:PROC     ;added by wd
  105.     EXTRN    output_newline:PROC    ;added by wd
  106.     
  107. ;number of command keys
  108. NUM_CMD_KEYS    EQU    (cmd_key_jumps-cmd_key_table)/2
  109.  
  110. ;+
  111. ; FUNCTION : get_kbd_line
  112. ;
  113. ;    Gets a line from the user and stores it in linebuf. The length
  114. ;    of the line is stored in global linelen. The name is a misnomer
  115. ;    because the line is from standard input, not necessarily from
  116. ;    the keyboard.
  117. ;
  118. ; Parameters:
  119. ;    None.
  120. ;
  121. ; Returns:
  122. ;    Nothing.
  123. ; Register(s) destroyed:
  124. ;-
  125.  
  126. get_kbd_line    proc    near
  127.     @save    si,di
  128.     mov    al,auto_recall
  129.     mov    auto_recall_on,al    ;Indicate if auto-recall is enabled
  130.     mov    continue_recall,1    ;Init auto-recall memory
  131.  
  132. ; Main editing loop
  133. @get_kbd_line_10:
  134.     mov    al,continue_recall
  135.     and    auto_recall_on,al    ;Indicate if we should keep
  136. ;                     auto-recalling
  137.     mov    continue_recall,0    ;Reset the flag. It will be set
  138. ;                     for the default actions keys.
  139.     call    near ptr disp_line    ;Show current line
  140.     shl    CycleFlags,1        ;shift the cycle_complete flag (wd)
  141.     mov    ah,getkey_funcnum    ;might be a raw keystroke (wd)
  142.     call    near ptr getkey        ;get next key from the user
  143.     and    CycleFlags,6        ;assume this cmd isn't a cycle_complete
  144. ;    mov    si,ax            ;si holds the character (not used--wd)
  145.     cmp    ax,32            ;Control character ?
  146.     jge    @get_kbd_line_15    ;No, then check if fn key
  147.     mov    di,ax            ;DI used to calculate
  148.     add    di,di            ;  offset into table
  149.     mov    ax,ctrl_key_redefs[di]    ;Mapping of key
  150. ;    mov    si,ax            ;(not used -- wd)
  151.     cmp    ax,32            ;Control char ?
  152.     jge    @get_kbd_line_15    ;No, then check if fn key
  153.     mov    di,ax            ;DI used to calculate
  154.     add    di,di            ;  offset into table
  155.     jmp    ctrl_key_table[di]    ;Branch according to control char
  156. @get_kbd_line_15:            ;Check if function key
  157.     cmp    ax,256+59        ;>= F1 ?
  158.     jb    @get_kbd_line_20    ;No, then check next table
  159.     cmp    ax,256+68        ;<= F10
  160.     jg    @get_kbd_line_20    ;Not fn key
  161.     jmp    @fn_key            ;Handle the function key
  162. @get_kbd_line_20:
  163.     cmp    ax,256+84        ;>= Shift-F1 ?
  164.     jb    @get_kbd_line_25    ;No, then check next table
  165.     cmp    ax,256+93        ;<= Shift-F10
  166.     jg    @get_kbd_line_25    ;
  167.     jmp    @sfn_key        ;Handle the shifted function key
  168. @get_kbd_line_25:
  169.     mov    cx,NUM_CMD_KEYS        ;size and...
  170.     mov    bx,offset DGROUP:cmd_key_table    ;beginning of jump table
  171. @get_kbd_line_30:            ;Loop begin
  172.     cmp    ax,cs:[bx]        ;Is this the key ?
  173.     je    @get_kbd_line_40    ;Hurrah, found
  174.     inc    bx            ;point to next key
  175.     inc    bx
  176.     loop    @get_kbd_line_30    ;If more keys, repeat
  177.     jmp    short @default_action    ;key not in table
  178. @get_kbd_line_40:            ;Jump to location associated with
  179.     jmp    word ptr cs:[bx+(2*NUM_CMD_KEYS)]    ;key
  180.  
  181. @quote:                    ;Insert next char
  182. ;                     without interpreting it
  183.     mov    ah,7            ;get a raw keystroke (wd)
  184.     call    near ptr getkey
  185.  
  186. @default_action:            ;Insert the character (in AX)
  187.     call    near ptr store_char
  188.     jc    @get_kbd_line_10    ;No room for char, keep looping
  189.     mov    al,auto_recall_on    ;Are we auto-recalling ?
  190.     or    al,al
  191.     jz    @get_kbd_line_10    ;No
  192.     call    near ptr execute_auto_recall
  193.     jc    @get_kbd_line_10    ;If carry set, no matching
  194. ;                     string in history buffer
  195.     mov    continue_recall,1    ;Else indicate auto-recall is
  196. ;                     still to go on
  197.     jmp    @get_kbd_line_10
  198.  
  199.  
  200. @char_left:                ;Cursor one char left
  201.     call    near ptr char_left    ;char_left will return to top
  202.     jmp    @get_kbd_line_10
  203. ;                     of editing loop
  204.  
  205. @char_right:                ;Cursor one char right
  206.     call    near ptr char_right    ;char_right will return to top
  207.     jmp    @get_kbd_line_10
  208. ;                     of editing loop
  209.  
  210. @word_left:                ;Cursor one word left
  211.     call    near ptr word_left
  212.     jmp    @get_kbd_line_10
  213.  
  214. @word_right:                ;Cursor one word right
  215.     call    near ptr word_right
  216.     jmp    @get_kbd_line_10
  217.  
  218. @bol:                    ;Beginning of line
  219.     call    near ptr go_bol
  220.     jmp    @get_kbd_line_10
  221.  
  222.  
  223. @eol:                    ;End of line
  224.     call    near ptr go_eol
  225.     jmp    @get_kbd_line_10
  226.  
  227.  
  228. @prev_line:                ;Get previous history line
  229.     mov    ax,offset DGROUP:hist_back
  230. @history_line:
  231.     call    ax
  232.     mov    ax,lastchar
  233.     mov    dot,ax            ;Leave cursor at end of line
  234. @history_search:
  235.     jnc    @history_line_done    ;Line found
  236.     call    near ptr strstk_settop    ;added by wd
  237.     call    near ptr bell        ;No line
  238. @history_line_done:
  239.     jmp    @get_kbd_line_10
  240.  
  241. @next_line:                ;Get next history line
  242.     mov    ax,offset DGROUP:hist_fwd
  243.     jmp    short @history_line
  244.  
  245. @search_back:                ;Search back thru history buffer
  246.     mov    ax,offset DGROUP:hist_bck_match
  247. @search:
  248.     mov    di,dot            ;Save current dot
  249.     call    ax
  250.     mov    dot,di            ;Restore it
  251.     jmp    short @history_search
  252.  
  253. @search_forw:                ;Search forward thru history buffer
  254.     mov    ax,offset DGROUP:hist_fwd_match
  255.     jmp    short @search
  256.  
  257. @cycle_complete:
  258.     or    CycleFlags,1
  259. @complete:                ;Try to find a matching filename
  260.     call    near ptr match_file
  261.     cmp    auto_recall_on,1    ;Autorecall ongoing?
  262.     je    short @del_eol        ;Yes, then delete to end of line
  263.     jmp    @get_kbd_line_10
  264.  
  265. @del_left:                ;Delete char before cursor
  266.     mov    ax,offset dgroup:char_left
  267.     jmp    short @delete
  268.  
  269. @del_right:                ;Delete char at cursor
  270.     mov    ax,offset dgroup:char_right
  271.     jmp    short @delete
  272.  
  273.  
  274. @del_prev_word:                ;Delete upto word beginning
  275.     mov    ax,offset dgroup:word_left
  276.     jmp    short @delete
  277.  
  278. @del_next_word:                ;Delete to start of next word
  279.     mov    ax,offset dgroup:word_right
  280.     jmp    short @delete
  281.  
  282. @del_bol:                ;Delete to beginning of line
  283.     mov    ax,offset dgroup:go_bol
  284.     jmp    short @delete
  285.  
  286.  
  287. @toggle_insert:
  288.     mov    ax,1
  289.     xor    al,edit_mode        ;Toggle edit mode
  290.     mov    edit_mode,al
  291.     xchg    ax,bx
  292.     add    bx,bx            ;Word offset
  293.     mov    cx,omode_cursor[bx]    ;cx<-cursor shape
  294.     mov    ah,01h            ;Set cursor size function
  295.     IF    TOGGLE_CURSOR
  296.     int    10h            ;BIOS 
  297.     ENDIF
  298.     jmp    @get_kbd_line_10    ;Repeat editing loop
  299.  
  300. @abort_and_store:            ;Erases current line but remembers
  301. ;                     it in the history buffer
  302.     call    near ptr remember
  303. ;    Fall through to erase line
  304. @erase_line:
  305.     call    near ptr go_bol        ;Move dot to beginning of line
  306. ;    fall thru to delete to end of line
  307.  
  308. @del_eol:                ;Delete to end of line
  309.     mov    ax,offset dgroup:go_eol
  310.  
  311. @delete:                ;General purpose delete
  312.     mov    si,dot            ;Remember the dot
  313.     call    ax            ;Move dot to new position
  314.     xchg    si,ax
  315.     call    near ptr erase_to_dot    ;Delete characters between ax and dot
  316.     jmp    @get_kbd_line_10
  317.  
  318. @twiddle:                ;added by wd
  319.     mov    si,dot
  320.     cmp    si,lastchar
  321.     jne    @twiddle_10
  322.  
  323.     call    near ptr char_left
  324.     jc    @ignore
  325.     dec    si
  326.  
  327. @twiddle_10:
  328.     call    near ptr char_left
  329.     jc    @ignore
  330.  
  331.     xor    ah,ah
  332.     push    ax
  333.     xchg    si,ax
  334.     call    near ptr erase_to_dot
  335.     call    near ptr char_right
  336.     pop    ax
  337.     jmp    @default_action
  338.  
  339. @cooked_char:                ;added by wd
  340.     mov    ah,8            ;get a cooked keystroke (wd)
  341.     call    near ptr getkey
  342.     jmp    @default_action
  343.  
  344. @autorecall:
  345.     xor    auto_recall,1        ;Toggle auto recall mode
  346.     jmp    @get_kbd_line_10
  347.  
  348. @macro:                 ;added by dfa
  349.     xor    disable_macro,1     ;Toggle macro,symbol expansion disable
  350.     jmp    @get_kbd_line_10
  351.  
  352.  
  353. @vars:
  354. ; Expand the variables on the line.
  355.     call    near ptr expand_var
  356.     jmp    @get_kbd_line_10    ;Ignore return status from expand_var
  357.  
  358.  
  359. @ignore:
  360.     jmp    @get_kbd_line_10    ;Ignore the character
  361.  
  362.  
  363. ctrl_key_table    LABEL    WORD
  364.     dw    @ignore        ;NUL or ^@
  365.     dw    @bol        ;^A
  366.     dw    @char_left    ;^B
  367.     dw    @cooked_char    ;^C (changed by wd - was @ignore)
  368.     dw    @del_right    ;^D
  369.     dw    @eol        ;^E
  370.     dw    @char_right    ;^F
  371.     dw    @abort_and_store ;^G
  372.     dw    @del_left    ;^H
  373. TAB_key_function label word    ; (label added by dfa)
  374.     dw    @complete    ;^I
  375.     dw    @vars        ;^J might have to be @ignore in order for input 
  376. ;                 redirection to work properly but try for
  377. ;                 var expansion anyway.
  378.     dw    @del_eol    ;^K
  379.     dw    @del_prev_word    ;^L
  380.     dw    @done_editing    ;^M
  381.     dw    @next_line    ;^N
  382.     dw    @del_eol_exec    ;^O
  383.     dw    @prev_line    ;^P (changed by wd - was @ignore)
  384.     dw    @quote        ;^Q
  385.     dw    @search_back    ;^R
  386.     dw    @ignore        ;^S
  387.     dw    @twiddle    ;^T (changed by wd - was @ignore)
  388.     dw    @prev_line    ;^U
  389.     dw    @search_forw    ;^V
  390.     dw    @del_next_word    ;^W
  391.     dw    @del_bol    ;^X
  392.     dw    @autorecall    ;^Y
  393.     dw    @default_action    ;^Z
  394. ESC_key_function label word    ; (label added by dfa)
  395.     dw    @erase_line    ;^[ or ESC
  396. BKS_key_function label word    ; (label added by wd)
  397.     dw    @cycle_complete    ;^\
  398.     dw    @ignore        ;^]
  399.     dw    @done_wipeout    ;^^
  400.     dw    @macro        ;^_ (changed by dfa - was @ignore)
  401.  
  402. cmd_key_table:                ;table of command keys
  403.     dw    127    ;DEL
  404.     dw    327    ;HOME
  405.     dw    328    ;UP
  406.     dw    331    ;LEFT
  407.     dw    333    ;RIGHT
  408.     dw    335    ;END
  409.     dw    336    ;DOWN
  410.     dw    338    ;INS
  411.     dw    339    ;KDEL
  412.     dw    371    ;CTLLEFT
  413.     dw    372    ;CTLRIGHT
  414. cmd_key_jumps:
  415.     dw    @del_left    ;DEL
  416.     dw    @bol        ;HOME
  417.     dw    @prev_line    ;UP
  418.     dw    @char_left    ;LEFT
  419.     dw    @char_right    ;RIGHT
  420.     dw    @eol        ;END
  421.     dw    @next_line    ;DOWN
  422.     dw    @toggle_insert    ;INS
  423.     dw    @del_right    ;KDEL
  424.     dw    @word_left    ;CTLLEFT
  425.     dw    @word_right    ;CTLRIGHT
  426.  
  427.  
  428. @sfn_key:
  429. ; A shifted function key has been struck.
  430. ; (Treat same as an unshifted function key).
  431. @fn_key:
  432. ; A function key has been struck.
  433.     call    near ptr expand_fnkey
  434.     jc    @fn_key_20            ;Error or no expansion
  435.     or    dx,dx                ;Line to be executed
  436. ;                         immediately ?
  437.     je    short @done_editing_2        ;Yes, all done
  438. @fn_key_20:
  439.     jmp    @get_kbd_line_10        ;else keep editing
  440.  
  441. @del_eol_exec:                ;Deletes characters from the dot
  442. ;                     to end of the line and then
  443. ;                     executes the line
  444.     mov    si,dot            ;Remember the dot
  445.     call    go_eol
  446.     xchg    si,ax
  447.     call    near ptr erase_to_dot
  448.     jmp    short @done_editing
  449.  
  450.  
  451. @done_wipeout:
  452. ; The line is executed. However it is not stored in the history buffer and
  453. ; is also removed from the screen (this is a little klugy).
  454.     mov    ax,offset DGROUP:linebuf
  455.     mov    dot,ax
  456.     mov    dx,lastchar
  457.     mov    lastchar,ax            ;Temporarily pretend line
  458. ;                         is empty
  459.     xchg    ax,dx
  460.     push    ax
  461.     call    near ptr set_disp_marks
  462.     call    disp_line
  463.     pop    ax
  464.     mov    lastchar,ax            ;Restore line length
  465.     jmp    short @get_kbd_line_90
  466.  
  467. @done_editing:
  468.     call    near ptr remember    ;Store in history buffer
  469. ;                     Picks up line from global linebuf
  470. @done_editing_2:
  471.     call    near ptr disp_line    ;Necessry for @del_eol_exec,
  472. ;                     might as well do for others
  473.     mov    ax,lastchar
  474.     mov    dot,ax            ;Set dot to end of line
  475.     call    near ptr line_to_scr    ;Set cursor beyond last character
  476.  
  477. @get_kbd_line_90:
  478.     @DispCh CR            ;Do a carraige return because
  479. ;                     some applications like EDLIN
  480. ;                     only do a LF to go to next line
  481. ;    @DispCh LF            ;Go onto next line
  482. ;    all done
  483. @get_kbd_line_99:
  484.     @restore
  485.     ret
  486. get_kbd_line endp
  487.  
  488.  
  489.  
  490. ;+
  491. ; FUNCTION : getkey
  492. ;
  493. ;    Read a keystroke, interpreting function keys into a 16-bit value.
  494. ;
  495. ; Parameters:
  496. ;    AH    = 7 for a raw keystroke, 8 for a cooked keystroke
  497. ;
  498. ; Returns:
  499. ;    AX    = 16-bit key value
  500. ; Register(s) destroyed:
  501. ;    DL
  502. ;-
  503. ; Requires AH be set to either 7 (raw) or 8 (cooked)
  504. getkey proc near
  505.     mov    dl,ah
  506.     int    21h
  507.     mov    ah,0
  508.     or    al,al
  509.     jne    @114        ;not '\0'
  510.     mov    ah,0Bh
  511.     int    21h        ;check if key available
  512.     or    al,al
  513.     jz    @113        ;no character available
  514.     mov    ah,dl
  515.     int    21h
  516.     mov    ah,1
  517.     jmp    short @114
  518. @113:
  519.     xor    ax,ax
  520. @114:
  521.     ret
  522. getkey    endp
  523.  
  524.  
  525.  
  526. ;+
  527. ; FUNCTION : expand_fnkey
  528. ;
  529. ;    Inserts the expansion corresponding to a symbol key into the
  530. ;    linebuffer. If the buffer is too small, only as many characters as
  531. ;    possible are inserted and the function returns an error. The
  532. ;    function also returns an error if the symbols is not defined. The
  533. ;    function also updates the displayed line. The function also checks
  534. ;    if the line is to be executed immediately or not, based on the last
  535. ;    character of the fn key expansion.
  536. ;
  537. ; Parameters:
  538. ;    AX    = function key character, must be between (256+59)-(256+68)
  539. ;          function keys and (256+84)-(256+93) for shifted functin keys.
  540. ;
  541. ; Returns:
  542. ;    CF    = 0 if no error, else 1
  543. ;          If CF is 1, then AX is 0 if symbol not found or non-zero
  544. ;          if symbol found but no room in line.
  545. ;    AX    = 1 if symbol was present 
  546. ;          0 if symbol was not found.
  547. ;    DX    = 0 if the line is to be executed immediately
  548. ;          non-0 otherwise
  549. ;          DX is only valid if CF=0 and AX=1
  550. ; Register(s) destroyed:
  551. ;     <TBA>
  552. ;-
  553. expand_fnkey proc near
  554.     @save    si,di
  555.     push    bp
  556.     mov    bp,sp
  557.     sub    sp,LINEBUF_SIZE
  558. exp_buf    equ <byte ptr [bp-LINEBUF_SIZE]>
  559.  
  560.     mov    si,offset DGROUP:fnkey_tab    ;SI->'SFn'
  561.     mov    dx,3                ;DX<-length of string
  562.     mov    di,si
  563.     sub    ax,256+59
  564.     cmp    ax,10                ;Is it a function key
  565.     jnb    @expand_fnkey_10        ;No, shifted function key
  566.     inc    si                ;SI->'Fn'
  567.     dec    dx                ;length of string is 2
  568.     jmp    short @expand_fnkey_15
  569. @expand_fnkey_10:
  570.     sub    ax,84-59
  571. @expand_fnkey_15:
  572.     cmp    ax,9                ;F10 must appear as F0
  573.     jne    @expand_fnkey_20
  574.     mov    al,'0'-'1'
  575. @expand_fnkey_20:
  576.     add    al,'1'
  577.     mov    2[di],al            ;Store in 'SFn' string
  578. ; OK now try and expand the symbol.
  579. ;                         SI->symbol
  580.     mov    ax,LINEBUF_SIZE
  581.     xchg    ax,dx                ;AX<-length of synbol
  582. ;                         DX<-length of expansion buffer
  583.     lea    di,exp_buf
  584.     call    near ptr get_symbol        ;Params SI,AX,DI,DX
  585.     jc    @expand_fnkey_99        ;No symbol (buffer too
  586. ;                         small case not possible).
  587. ;                         AX will be 0 for this case.
  588. ; OK now we have the symbol expansion, so try insert it into the linebuffer.
  589. ;    AX contains length of expansion
  590.     mov    si,di                ;SI->expansion
  591.     add    di,ax
  592.     dec    di                ;DI->last char of expansion
  593.     xor    dx,dx
  594.     mov    dl,byte ptr [di]        
  595.     sub    dl,fnkey_exec_char        ;Is this line to be
  596. ;                         immediately executed
  597.     jne    @expand_fnkey_80        ;No
  598.     dec    ax                ;The last char of expansion
  599. ;                         is a special char. Do not
  600. ;                         include it in the insert
  601. ;                         string 
  602. @expand_fnkey_80:
  603.     push    dx
  604.     call    near ptr insert_at_dot        ;Params SI,AX
  605. ;    pushf                    ;Save CF
  606. ;    call    disp_line
  607. ;    popf                    ;Restore CF
  608.     mov    ax,1                ;AX<-exit code
  609.     pop    dx                ;DX is 0 if line is to be
  610. ;                         executed immediately
  611. @expand_fnkey_99:
  612.     mov    sp,bp
  613.     pop    bp
  614.     @restore
  615.     ret
  616.  
  617. expand_fnkey endp
  618.  
  619.  
  620. ;+
  621. ; FUNCTION : store_char
  622. ;
  623. ;    Stores    the character in AX into the line buffer if max line
  624. ;    length will not be exceeded. Characters may be inserted or
  625. ;    overwrite chars in the buffer depending on the edit mode and whether
  626. ;    auto-recall is on.
  627. ;
  628. ; Parameters:
  629. ;    AX    = character
  630. ;
  631. ; Returns:
  632. ;    CF    = 0 if no error, else 1
  633. ; Register(s) destroyed:
  634. ;     <TBA>
  635. ;-
  636. store_char proc near
  637.     @save    si
  638.     cmp    ax,256            ;char >= 256
  639.     jnb    @store_char_90        ;Ignore if so
  640.     cmp    edit_mode,0        ;1 if insert mode
  641.     je    @store_char_20        ;Jump if overtype mode
  642.     cmp    auto_recall_on,1    ;Is auto-recall on ?
  643.     je    @store_char_20        ;Yes, behave as if in overtype mode
  644.     mov    si,offset dgroup:tempchar ;temporary storage
  645.     mov    [si],al            ;Store char
  646.     mov    ax,1            ;Length of string
  647.     call    near ptr insert_at_dot    ;Insert the character
  648.     jnc    @store_char_99        ;No problemo
  649.     jmp    short @store_char_90    ;No room in buffer
  650. @store_char_20:
  651.     mov    si,dot            ;Current position in line
  652.     cmp    si,LINEBUF_END        ;At line end?
  653.     jae    @store_char_90
  654. ;    Enough room for a char
  655.     mov    [si],al            ;Store the char
  656.     mov    dx,si            ;DX->changed character
  657.     mov    ax,si
  658.     inc    ax            ;AX->char after change
  659.     mov    dot,ax            ;Store it as new dot position
  660.     cmp    si,lastchar        ;Was it end of line ?
  661.     jb    @store_char_30
  662.     mov    lastchar,ax        ;Store new end of line
  663. @store_char_30:
  664.     call    near ptr set_disp_marks    ;ax,dx parameters
  665.     clc                ;Indicate no error
  666.     jmp    short @store_char_99
  667. @store_char_90:
  668.     call    near ptr bell
  669.     stc                ;Indicate error
  670. @store_char_99:
  671.     @restore
  672.     ret
  673. store_char endp
  674.  
  675.  
  676. ;+
  677. ; FUNCTION : word_left
  678. ;
  679. ;    Move one word left.
  680. ;
  681. ; Parameters:
  682. ;    Globals linebuf and dot.
  683. ;
  684. ; Returns:
  685. ;    CF = 1 if dot was at beginning of the line already
  686. ;         0 otherwise.
  687. ; Register(s) destroyed:
  688. ;-
  689. word_left proc near
  690. @word_left_10:
  691.     call    near ptr char_left    ;Move one char left
  692.     jc    @word_left_99        ;Already at beginning of line
  693. @word_left_12:
  694.     ;Loop to backup over non-alphanum
  695.     call    near ptr isalphnum    ;AL alphanumeric?
  696.     jnc    @word_left_15        ;Yes
  697.     call    near ptr char_left    ;One char left.
  698.                     ;AL<-char at dot
  699.     jnc    @word_left_12        ;Not at beginning of line
  700. @word_left_15:                ;Now backup to beginning of word
  701. ;    At this point, dot is always at a alphabetic char or beginning
  702. ;    of the line
  703.     call    near ptr char_left
  704.     jc    @word_left_98        ;Were already at beginning of line
  705.     call    near ptr isalphnum    ;Alphanumeric?
  706.     jnc    @word_left_15        ;Yes, loop back
  707.                     ;Found non-alphanumeric char
  708.     call    near ptr char_right    ;move over one
  709. @word_left_98:
  710.     clc                ;Clear carry flag
  711. @word_left_99:
  712.     ret
  713. word_left endp
  714.  
  715.  
  716.  
  717. ;+
  718. ; FUNCTION : word_right
  719. ;
  720. ;    Move one word right.
  721. ;
  722. ; Parameters:
  723. ;    Globals linebuf and dot.
  724. ;
  725. ; Returns:
  726. ;    Nothing.
  727. ; Register(s) destroyed:
  728. ;-
  729. word_right proc near
  730. @word_right_10:                ;Loop fwd over alphanumerics
  731.     call    near ptr char_right    ;One char right
  732.                     ;AL<-char at dot
  733.     jc    @word_right_99        ;Already at end of line
  734.     call    near ptr isalphnum    ;Is AL alphanumeric ?
  735.     jnc    @word_right_10        ;Yes, loop back
  736. @word_right_15:                ;Now move to beginning of word
  737.     call    near ptr char_right
  738.     jc    @word_right_99        ;Already at end of line
  739.     call    near ptr isalphnum    ;Alphanumeric?
  740.     jc    @word_right_15        ;Not alphanum char, loop back
  741. @word_right_99:
  742.     ret
  743. word_right endp
  744.  
  745.  
  746.  
  747.  
  748. ;+
  749. ; FUNCTION : char_left
  750. ;
  751. ;    Moves the 'dot' one character to the left unless
  752. ;    already at the beginning of the line.
  753. ;
  754. ; Parameters:
  755. ;    Global    dot is current position in the line.
  756. ;
  757. ; Returns:
  758. ;    AL    = char at new dot position.
  759. ;    CF    = 1 if OLD dot was at beginning of line
  760. ;          0 otherwise.
  761. ; Register(s) destroyed:
  762. ;-
  763. char_left proc    near
  764.     @save    si
  765.     mov    ax,dot            ;Current position in line
  766.     cmp    ax,offset dgroup:linebuf
  767.     jne    @char_left_5
  768.     stc                ;Dot already at beginning of line
  769.     jmp    short @char_left_99
  770. @char_left_5:
  771.     dec    ax            ;Move dot left
  772.     mov    dot,ax
  773. @char_left_99:
  774.     xchg    ax,si
  775.     lodsb                ;AL<-char at dot
  776.     @restore
  777.     ret
  778. char_left endp
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786. ;+
  787. ; FUNCTION : char_right
  788. ;
  789. ;    Moves the 'dot' one character to the right unless
  790. ;    already at the end of the line.
  791. ;
  792. ; Parameters:
  793. ;    Global    dot is current position in the line.
  794. ;
  795. ; Returns:
  796. ;    AL    = char at new dot position. Undefined if new dot is at
  797. ;          the end of the line.
  798. ;    CF    = 1 if OLD dot was already at end of the line.
  799. ;          0 otherwise.
  800. ; Register(s) destroyed:
  801. ;-
  802. char_right proc    near
  803.     @save    si
  804.     mov    si,dot            ;Current position in line
  805.     mov    ax,lastchar        ;AX->Beyond last char
  806.     dec    ax            ;AX->last char in line
  807.     cmp    ax,si            ;Dot at end ?
  808.     jc    @char_right_99        ;Already at line end
  809.     inc    si            ;Move dot right, CF not affected
  810.     mov    dot,si
  811.     lodsb                ;AL<-char at dot, (undefined if
  812. ;                     dot is now at end of line).
  813. ;    CF    already clear
  814. @char_right_99:
  815.     @restore
  816.     ret
  817. char_right endp
  818.  
  819.  
  820.  
  821. ;+
  822. ; FUNCTION : go_bol
  823. ;
  824. ;    Sets    dot to pint to the beginning of the line
  825. ;
  826. ; Register(s) destroyed: None.
  827. ;-
  828. go_bol    proc    near
  829.     mov    dot,offset dgroup:linebuf
  830.     ret
  831. go_bol    endp
  832.  
  833.  
  834.  
  835. ;+
  836. ; FUNCTION : go_eol
  837. ;
  838. ;    Sets    dot to pint to the end of the line
  839. ;
  840. ; Register(s) destroyed: AX.
  841. ;-
  842. go_eol    proc    near
  843.     mov    ax,lastchar
  844.     mov    dot,ax
  845.     ret
  846. go_eol    endp
  847.  
  848.  
  849.  
  850.  
  851. ;+
  852. ; FUNCTION : match_file
  853. ;
  854. ;    match_file tries to expand the filename to the left of the
  855. ;    cursor. If there are several matching files, the longest common
  856. ;    prefix is placed on the line.
  857. ;    Added by wd:    If no characters can be placed on the line,
  858. ;            list the possible matches.  Alternately, add
  859. ;            one match at a time to the line.
  860. ;
  861. ; Parameters:
  862. ;    None.
  863. ;
  864. ; Returns:
  865. ;    Nothing.
  866. ; Register(s) destroyed:
  867. ;-
  868. match_file proc    near
  869.     @save    si,di
  870.     push    bp
  871.     mov    bp,sp
  872.     sub    sp,64+44+2+2+2+2+2
  873. pathbuf        equ    64        ;Storage for entire filename with path
  874. ffblk        equ    pathbuf+44
  875. ffblk_attr     equ    ffblk-15h    ;Attr byte within ffblk
  876. ffblk_name     equ    ffblk-1Eh    ;filename within ffblk
  877. lineptr        equ    ffblk+2
  878. remaining    equ    lineptr+2    ;Remembers remaining space in path
  879. oldDTAseg     equ    remaining+2
  880. oldDTAoff     equ    oldDTAseg+2
  881. breakstate    equ    oldDTAoff+2    ;Remembers break state
  882.  
  883.     mov    ax,3300h        ;Get current break state
  884.     int    21h            ;DL<-current break state
  885.     mov    byte ptr [bp-breakstate],dl ;Remember it
  886.     xor    dl,dl
  887.     mov    ax,3301h        ;Disable break check during
  888. ;                     disk i/O
  889.     int    21h
  890.  
  891.     push    es
  892.     @GetDTA                ;Get and save old DTA
  893.     mov    [bp-oldDTAseg],es
  894.     mov    [bp-oldDTAoff],bx
  895.     pop    es
  896. ;
  897.     lea    dx,[bp-ffblk]
  898.     @SetDTA    dx            ;Set DTA to our DTA
  899.  
  900. ; If the last call was also a cycle, continue what we started (wd,dfa)
  901.     cmp    CycleFlags,7
  902.     je    @match_file_60
  903.  
  904. ;    lea    di,[bp-pathbuf]        ;OK 'cause SS==DS (removed by wd)
  905.     mov    si,dot            ;Current line position
  906.     mov    olddot,si        ;Remember current dot position (wd)
  907.     mov    cx,63            ;Max length of path
  908. @match_file_10:
  909.     cmp    si,offset dgroup:linebuf
  910.     je    @match_file_51        ;Beginning of line and filename
  911.     dec    si
  912.     mov    al,[si]            ;AL<-next char
  913. @match_file_25:
  914.     call    near ptr isspace
  915.     je    @match_file_50        ;Beginning of filename
  916. @match_file_45:                ;Check for next char if
  917. ;                     pathname not too long
  918.     loop    @match_file_10
  919.     jmp    @match_file_90        ;Pathname too long, just exit
  920. @match_file_50:
  921.     inc    si
  922. @match_file_51:
  923.     mov    [bp-lineptr],si        ;Save start of path name in linebuf
  924.     mov    ax,63
  925.     sub    ax,cx            ;Length of name
  926.     mov    [bp-remaining],cx    ;remember num bytes left in pathbuf
  927.     xchg    ax,cx            ;CX<-length of name
  928. ;    jcxz    @match_file_90        ;No name, just exit (removed by wd)
  929.  
  930.     call    near ptr @match_file_parse
  931.  
  932.     lea    dx,[bp-pathbuf]        ;dx->ASCII name
  933.     @GetFirst dx,16            ;Include subdirs in search
  934.     jnc    @match_file_70        ;No error
  935. @match_file_58:
  936.     mov    ffblk_save,0        ;Make sure the DTA will fail a GetNext
  937.     call    near ptr bell        ;No files found
  938.     jmp    @match_file_90        ;Restore DTA and exit 
  939.  
  940. @match_file_60:
  941.     mov    cx,FFBLK_SAVE_SIZE/2    ;5 lines by dfa and wd
  942.     mov    si,offset ffblk_save
  943.     lea    di,[bp-ffblk]
  944.     rep     movsw            ;restore the DTA for the GetNext
  945.     and    CycleFlags,3        ;Don't need more than this now
  946. @match_file_65:
  947.     @GetNext            ;Get the next file name
  948.     jnc    @match_file_70        ;Got one
  949.     mov    ax,olddot        ;AX->start of chars to be deleted
  950.     call    near ptr erase_to_dot    ;Delete characters between dot
  951.     mov    CycleFlags,1            ;If next key is cycle,  want to do
  952.     jmp    short @match_file_58    ;it immediately
  953.  
  954. @match_file_70:                ;At least one file found
  955.     lea    di,[bp-pathbuf]        ;DI->pathbuf
  956.     lea    si,[bp-ffblk_name]    ;Name returned by GetFirst
  957.     cmp    byte ptr [si],'.'    ;Is this '.' or '..'?
  958.     je    @match_file_65        ;Yes, ignore it
  959. @match_file_71:                ;Copy the file name
  960.     lodsb
  961.     stosb
  962.     or    al,al
  963.     jne    @match_file_71
  964.  
  965.     mov    ax,SPACE        ;If file, add a space (ah = 0 -- wd)
  966.     test    byte ptr [bp-ffblk_attr],16 ;Subdirectory?
  967.     je    @match_file_72        ;No
  968.     mov    al,backslash_char    ;If subdir, (possibly) add a backslash
  969. @match_file_72:
  970.     mov    word ptr [di-1],ax    ;Add a space or a '\' and a null
  971.  
  972.     cmp    CycleFlags,3        ;If cycling, bug out (wd,dfa)
  973.     je    @match_file_79
  974.  
  975. ;    Now hunt for more files. For each file found, keep the longest 
  976. ;    prefix in common so far.
  977.  
  978.     @GetNext            ;Get the next file name
  979.     jc    @match_file_80        ;No more files
  980.  
  981.     lea    di,[bp-pathbuf]        ;DI->start of file name
  982.     lea    si,[bp-ffblk_name]    ;Name returned by GetNext
  983.     mov    cx,13            ;Max Length of field
  984.     repe    cmpsb            ;Compare strings
  985.     xor    ax,ax            ;Terminating null for [di-1]
  986.     jmp    short @match_file_72    ;Try for more files
  987.  
  988. @match_file_79:
  989.     mov    cx,FFBLK_SAVE_SIZE/2    ;4 lines by dfa and wd
  990.     lea    si,[bp-ffblk]
  991.     mov    di,offset ffblk_save
  992.     rep    movsw            ;save ffblk for next call
  993.  
  994. @match_file_80:
  995. ;    Found one or more files, copy the longest common prefix
  996. ;    into the line buffer
  997. ;following 2 lines moved by wd
  998. ;    mov    ax,[bp-lineptr]        ;AX->start of chars to be deleted
  999. ;    call    near ptr erase_to_dot    ;Delete characters between dot
  1000. ;                     and start of name
  1001.     lea    si,[bp-pathbuf]        ;SI->name to be copied
  1002.     mov    di,si
  1003.     xor    al,al
  1004.     mov    cx,64
  1005.     repne    scasb            ;Hunt for terminating null
  1006.     mov    ax,63
  1007.     sub    ax,cx            ;AX<-length of string
  1008.  
  1009. ;following 10 lines added by wd & dfa
  1010.     cmp    CycleFlags,3        ;If cycling, no length check
  1011.     je    @match_file_85
  1012.     mov    dx,dot
  1013.     sub    dx,fnameptr        ;DX<-length of search string
  1014.     cmp    ax,dx
  1015.         ja      @match_file_85          ;If cycling,  we want first call
  1016.         jb      @match_file_list        ;not to actually cycle,  but just
  1017.     test    CycleFlags,1            ;complete to longest common prefix
  1018.         jz        @match_file_list
  1019.        jbe    @match_file_list
  1020.  
  1021. @match_file_85:
  1022.     test    CycleFlags,1
  1023.     jnz    @match_file_87             ;If next key is cycle,  want to do
  1024.     mov    CycleFlags,1           ;it immediately (dfa)
  1025.  
  1026. @match_file_87:
  1027. ; SI->string, AX is length
  1028.     push    ax
  1029.     call    near ptr xlate_lower    ;Convert to lowercase
  1030. ;ok, these 2 lines removed above can now do their work - wd
  1031.     mov    ax,fnameptr        ;AX->start of chars to be deleted
  1032.     call    near ptr erase_to_dot    ;Delete chars between dot and start
  1033.     pop    ax    
  1034.     call    near ptr insert_at_dot    ;SI->source, AX == length
  1035.  
  1036. @match_file_90:
  1037.     push    ds
  1038.     mov    ds,[bp-oldDTAseg]
  1039.     mov    dx,[bp-oldDTAoff]
  1040.     @SetDTA    dx            ;Restore DTA
  1041.     pop    ds
  1042. ; Restore previous state of break checking
  1043.     mov    dl,byte ptr [bp-breakstate]
  1044.     mov    ax,3301h
  1045.     int    21h
  1046.     mov    sp,bp
  1047.     pop    bp
  1048.     @restore
  1049.     ret
  1050.  
  1051. ; remainder of this file extensively modified by wd
  1052. @match_file_list:
  1053.     mov    CycleFlags,1            ;If next key is cycle,  want to do
  1054.                        ;it immediately (dfa)
  1055.     mov    si,[bp-lineptr]
  1056.     mov    cx,dot
  1057.     sub    cx,si
  1058.     call    near ptr @match_file_parse
  1059.  
  1060.     call    near ptr output_newline
  1061.     lea    dx,[bp-pathbuf]
  1062.     @GetFirst dx,16
  1063.  
  1064. @match_file_list_10:
  1065.     lea    si,[bp-ffblk_name]
  1066.     cmp    byte ptr [si],'.'    ;Is this '.' or '..'?
  1067.     je    @match_file_list_55    ;Yes, ignore it
  1068.     mov    cx,15
  1069.  
  1070. @match_file_list_20:
  1071.     lodsb
  1072.     test    al,al
  1073.     jz    @match_file_list_30
  1074.     call    near ptr tolower
  1075.     @DispCh al
  1076.     dec    cx
  1077.     jmp    @match_file_list_20
  1078.  
  1079. @match_file_list_30:
  1080.     mov    al,SPACE
  1081.     test    byte ptr [bp-ffblk_attr],16    ;Subdirectory?
  1082.     je    @match_file_list_40        ;No
  1083.     mov    al,'\'                ;If subdir, add a backslash
  1084. @match_file_list_40:
  1085.     @DispCh al
  1086. @match_file_list_50:
  1087.     @DispCh SPACE
  1088.     loop    @match_file_list_50
  1089. @match_file_list_55:
  1090.     @GetNext
  1091.     jnc    @match_file_list_10
  1092.  
  1093.     call    near ptr get_curpos        ;DX<-current cursor position
  1094.     test    dl,dl
  1095.     jz    @match_file_list_60
  1096.     call    near ptr output_newline
  1097. @match_file_list_60:
  1098.     call    near ptr disp_prompt
  1099.     call    near ptr get_curpos        ;DX<-current cursor position
  1100.     mov    initial_currow,dh
  1101.     mov    ax,lastchar
  1102.     mov    dx,offset DGROUP:linebuf
  1103.     call    near ptr set_disp_marks
  1104.     call    disp_line            ;Redisplay line
  1105.     jmp    @match_file_90
  1106. match_file endp
  1107.  
  1108. @match_file_parse proc near
  1109. ;   Copy filename into ASCIIZ buffer
  1110. ;   SI->first char of filename in line buffer, CX=length
  1111.     xor    dx,dx            ;Flags
  1112.     lea    di,[bp-pathbuf]        ;OK 'cause SS==DS
  1113.     mov    fnameptr,si        ;Assumed start of filename in linebuf
  1114.     jcxz    @match_file_p42
  1115. @match_file_p0:
  1116.     lodsb                ;AL<-next char
  1117.     stosb                ;Store it
  1118.     cmp    al,'.'
  1119.     jne    @match_file_p10
  1120.     or    dl,1            ;Set flag to remember file type '.'
  1121.     jmp    short @match_file_p40    ;Check out next character
  1122. @match_file_p10:
  1123.     cmp    al,':'            ;Disk?
  1124.     je    @match_file_p30
  1125.     cmp    al,'\'            ;Directory separator?
  1126.     je    @match_file_p20
  1127.     cmp    al,'/'            ;Same thing
  1128.     jne    @match_file_p40
  1129. @match_file_p20:
  1130.     cmp    backslash_char,0    ;is backslash appending turned on?
  1131.     je    @match_file_p30        ;no
  1132.     mov    backslash_char,al    ;remember the type of slash (/ or \)
  1133. @match_file_p30:
  1134.     mov    fnameptr,si        ;Update start of filename in linebuf
  1135.     and    dl,0FEh            ;Forget file type flag
  1136.  
  1137. @match_file_p40:
  1138.     loop    @match_file_p0
  1139.  
  1140. @match_file_p42:
  1141.     mov    cx,[bp-remaining]    ;CX<-remaining space
  1142.     jcxz    @match_file_p50        ;Only space for terminator
  1143.     mov    al,'*'
  1144.     stosb                ;Attach a '*'
  1145.     cmp    cl,3            ;Enough space for ".*"
  1146.     jb    @match_file_p50
  1147.     and    dl,1            ;Saw a file type ?
  1148.     jne    @match_file_p50        ;Yes, go attach terminator
  1149.     mov    [di],2A2Eh        ;Attach a ".*"
  1150.     inc    di
  1151.     inc    di
  1152. @match_file_p50:
  1153.     xor    al,al            ;AL<-0
  1154.     stosb                ;Terminating 0
  1155.     ret
  1156. @match_file_parse endp
  1157.  
  1158.  
  1159. CSEG    ENDS
  1160.  
  1161.     END
  1162.